#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
import paramiko
import sys
import json
import time
import telnetlib
import datetime

import OssUpload
import LocalStorage
import TextDiff
import QQSendEmail
import YandexSendEmail
import ZipFolder


def xstr(s):
    if s is None:
        return ""
    else:
        return s

def sshconfig(ip, port, username, password, cmd, PS1, isNeedEnableMode, enablePassword, promptUser,
              isNeedSecondaryConfirmation):
    # 实例化SSHClient
    client = paramiko.SSHClient()
    # 自动添加策略，保存服务器的主机名和密钥信息
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    # 连接SSH服务端，以用户名和密码进行认证
    client.connect(hostname=ip, username=username, password=password, look_for_keys=False)
    chan = client.invoke_shell()
    chan.settimeout(9000)

    if (isNeedSecondaryConfirmation is None) or len(isNeedSecondaryConfirmation) < 1:
        # 不处理登陆
        print ("不需要二次确认")
    else:
        print ("需要二次确认")
        # 处理登录
        # 输入登录用户名

        if (promptUser is None) or len(promptUser) < 1:
            promptUser = 'Username:'
        welcomeinfo = ''
        while True:
            line = chan.recv(4096)
            line = line.decode('ascii')
            welcomeinfo += line
            if promptUser in line:
                break
        print (welcomeinfo)
        chan.send(username + '\n')
        while True:
            line = chan.recv(4096)
            line = line.decode('ascii')
            welcomeinfo += line
            if 'Password:' in line:
                break
        print (welcomeinfo)
        chan.send(password + '\n')

    # 获取登陆后的消息
    welcomeinfo = ''
    while True:
        line = chan.recv(4096)
        welcomeinfo += line.decode('ascii')
        if (PS1 is not None) & (len(PS1) > 0):
            isFindPS1 = False
            for i in range(len(PS1)):
                if PS1[i] in line.decode('ascii'):
                    isFindPS1 = True
            if isFindPS1 == True:
                break
    print (welcomeinfo)

    if isNeedEnableMode == "1":
        chan.send('enable' + '\n')
        chan.send(enablePassword + '\n')
        # 获取特权后的消息
        enableInfo = ''
        while True:
            line = chan.recv(4096)
            enableInfo += line.decode('ascii')
            if (PS1 is not None) & (len(PS1) > 0):
                isFindPS1 = False;
                for i in range(len(PS1)):
                    if PS1[i] in line.decode('ascii'):
                        isFindPS1 = True
                if isFindPS1 == True:
                    break;
        print (enableInfo)

    chan.send(cmd + '\n')
    result = ''
    # more交互处理
    more = '-- More --'
    more2 = '--More--'
    more3 = '<--- More --->'
    more4 = '-- More --'
    more5 = '--More'
    enterMsg = 'Press Enter to continue'
    #  循环获取数据
    while True:
        line = chan.recv(4096)
        line = line.decode('ascii')
        # print line
        result += line
        if (more in line) | (more2 in line) | (more3 in line) | (more4 in line) | (more5 in line):
            chan.send(" ")
            continue;
        if enterMsg in line:
            chan.send("\n")
            continue;
        if (PS1 is not None) & (len(PS1) > 0):
            isFindPS1 = False;
            for i in range(len(PS1)):
                if PS1[i] in line:
                    isFindPS1 = True
            if isFindPS1 == True:
                break;
    client.close()
    print (result)
    return result


def telnetconfig(ip, port, username, password, cmd, PS1, isNeedEnableMode, enablePassword, promptUser):
    # 连接Telnet服务器
    tn = telnetlib.Telnet(ip, port=23, timeout=10)
    tn.set_debuglevel(2)
    # 处理登录
    # 输入登录用户名
    if (promptUser is None) or len(promptUser) < 1:
        tn.read_until('Username:')
    else:
        tn.read_until(promptUser)
    tn.write(username.encode('ascii') + '\n')

    # 输入登录密码
    tn.read_until('Password:')
    tn.write(password.encode('ascii') + '\n')

    time.sleep(2)

    # 获取登陆后的消息
    welcomeinfo = ""
    while True:
        line = tn.read_very_eager().encode("ascii")
        welcomeinfo += line
        if (PS1 is not None) & (len(PS1) > 0):
            isFindPS1 = False
            for i in range(len(PS1)):
                if PS1[i] in line:
                    isFindPS1 = True
            if isFindPS1 == True:
                break
    print (welcomeinfo)

    # 处理特权密码
    if isNeedEnableMode == "1":
        tn.write('enable'.encode('ascii') + '\n')
        tn.write(enablePassword.encode('ascii') + '\n')
        time.sleep(2)
        # 获取特权后的消息
        enableInfo = ''
        while True:
            line = tn.read_very_eager().encode("ascii")
            enableInfo += line
            if (PS1 is not None) & (len(PS1) > 0):
                isFindPS1 = False
                for i in range(len(PS1)):
                    if PS1[i] in line:
                        isFindPS1 = True
                if isFindPS1 == True:
                    break
        print (enableInfo)

    tn.write(cmd.encode('ascii') + '\n')
    time.sleep(2)
    result = ''
    # more交互处理
    more = '-- More --'
    more2 = '--More--'
    more3 = '<--- More --->'
    more4 = '-- More --'
    #  循环获取数据
    while True:
        line = tn.read_very_eager().encode("ascii")
        result += line
        if (more in line) | (more2 in line) | (more3 in line) | (more4 in line):
            tn.write(" ".encode('ascii'))
            time.sleep(2)
            continue
        if (PS1 is not None) & (len(PS1) > 0):
            isFindPS1 = False
            for i in range(len(PS1)):
                if PS1[i] in line:
                    isFindPS1 = True
            if isFindPS1 == True:
                break
    tn.close()
    print (result)
    return result

def strdelsub(str,num1,num2):
    return str[:num1] + str[num2+1:];

def strdelmore(str):
    template1 = ['\r\n', '\x1b[42D', '\x1b[42D']
    template2 = ['\r\n', '--->\r', '    \r']
    template3 = ['\r\n', '\x08\x08\x08\x08\x08\x08\x08\x08\x08', '\x08\x08\x08\x08\x08\x08\x08\x08\x08']
    template4 = ['\n', '\r\n', '(q)uit\r\n']
    template=[template1,template2,template3,template4]
    for item in template:
        #print item
        if (str.find(item[2]) >= 0 and str.find(item[1]) >= 0):
            while len(str) > 0 and str.find(item[2]) >= 0:
                index1 = str.rfind(item[2], 0, len(str))
                index2 = str.rfind(item[1], 0, index1)
                index3 = str.rfind(item[0], 0, index2)
                str = strdelsub(str, index3 + len(item[0]), index1 + len(item[2]) - 1)
            return str
    return str

def main():
    file = open("SwitchConfig.json", "rb")
    fileJson = json.load(file)
    switch = fileJson["switch"]
    backFileMode = fileJson["backFileMode"]
    #备份文件
    for i in range(len(switch)):
        print (switch[i])
        if switch[i]["protocol"] == "ssh":
            if 'isNeedSecondaryConfirmation' in switch[i]  and switch[i]["isNeedSecondaryConfirmation"] == "1":
                result = sshconfig(switch[i]["ip"], switch[i]["port"], switch[i]["username"], switch[i]["password"],
                                   switch[i]["cmd"], switch[i]["PS1"], switch[i]["isNeedEnableMode"],
                                   switch[i]["enablePassword"], switch[i]["promptUser"], switch[i]["isNeedSecondaryConfirmation"])
            else:
                result = sshconfig(switch[i]["ip"], switch[i]["port"], switch[i]["username"], switch[i]["password"],
                                   switch[i]["cmd"], switch[i]["PS1"], switch[i]["isNeedEnableMode"],
                                   switch[i]["enablePassword"],None,None)

            if backFileMode =="local":
                LocalStorage.uploadFile(switch[i]["fileName"], strdelmore(result))
            elif backFileMode =="oss":
                OssUpload.uploadFile(switch[i]["fileName"], strdelmore(result))

        if switch[i]["protocol"] == "telnet":
            if switch[i].has_key('promptUser') :
                result = telnetconfig(switch[i]["ip"], switch[i]["port"], switch[i]["username"], switch[i]["password"],
                                      switch[i]["cmd"], switch[i]["PS1"], switch[i]["isNeedEnableMode"],
                                      switch[i]["enablePassword"], switch[i]["promptUser"])
            else:
                result = telnetconfig(switch[i]["ip"], switch[i]["port"], switch[i]["username"], switch[i]["password"],
                                      switch[i]["cmd"], switch[i]["PS1"], switch[i]["isNeedEnableMode"],
                                      switch[i]["enablePassword"], None)
            if backFileMode == "local":
                LocalStorage.uploadFile(switch[i]["fileName"], strdelmore(result))
            elif backFileMode == "oss":
                OssUpload.uploadFile(switch[i]["fileName"], strdelmore(result))
    # 文件对比 今日和昨日的对比
    mailContent = ""
    for i in range(len(switch)):
        print (switch[i])
        fileName = switch[i]["fileName"]
        yesterday = datetime.date.today() + datetime.timedelta(-1);
        dateFolder1 = yesterday.strftime("%Y%m%d")
        dateFolder2 = datetime.datetime.now().strftime("%Y%m%d")
        if backFileMode == "local":
            text1 = LocalStorage.readFile(dateFolder1, fileName)
            text2 = LocalStorage.readFile(dateFolder2, fileName)
            if text1 is not None and text2 is not None:
                # 读取本地文件
                result = TextDiff.getTextDiff(text1, text2)
                mailContent = mailContent + fileName + "对比结果：\n" + xstr(result) + "\n"
            else:
                result = "发现对比文件缺失，可能是新文件或未读取到\n" +"文件名"+fileName+"\n"+ "旧文件：" + xstr(text1) + "\n新文件：" + xstr(
                    text2) + "\n"
                mailContent = mailContent + result
    #print "mailContent"
    print (mailContent)
    mailtitle = "交换机配置文件变更检测" + datetime.datetime.now().strftime("%Y%m%d")
    zip1 = ZipFolder.ZipFolder(dateFolder1, dateFolder1)
    zip2 = ZipFolder.ZipFolder(dateFolder2,dateFolder2)
    zipfileNames = [zip1,zip2]
    YandexSendEmail.YandexsendMailWithAttach(mailtitle, mailContent, "980227548@qq.com",zipfileNames)
    sys.exit(0)


if __name__ == '__main__':
    main()
